(function($){    
    //默认配置.    
    var _defaultConfig = {
        closable : false,
        searchable : true,   
        isAlwaysShow : false,   //TreeNodeSelector一般用于下拉菜单中选择节点，所有默认是隐藏的，使用时由$selectorTrigger元素触发显示。
        mode : 'common',    // common|isSelectHidden
        exclusion : []  //需要排除(不显示)的节点.        
    };    
    /**
     * 节点点击事件.
     * @event selectNode
     */
    var EVT_SelectNode = 'selectNode';   
    /**
     * 节点加载完成时事件.
     * @event rootLoaded 
     */
    var EVT_RootLoaded = 'rootLoaded'; 
    
    /**
     * 树型节点选择控件. 
     * TODO : 清除特定代码.
     */
    
    /**
     * 构造函数. 
     * @param {Selector} $trigger
     * @param {Object} config
     */
    var _TreeNodeSelector = function ($trigger, config){
        var _this = this;
        $trigger = $($trigger);
        Observable.enable(this);
                
        this.config = $.extend({}, _defaultConfig, config);
        this.$wrapper = $([
            '<div class="treeNodeSelectorWrapper">',
                '<div class="searchNodeBox"></div>',
                '<div class="treeNodeSelector"></div>',
            '</div>'
        ].join(''));
        this.$wrapper.style(this.config['style']);
                
        this.$searchBox = this.$wrapper.find('.searchNodeBox');
        this.$tree = this.$wrapper.find('.treeNodeSelector');
        //数据适配器.
        this.dataAdapter = new (this.config['nodeDataAdapter'] || DataAdapter)();        
        //关闭按钮.
        if(this.config['closable'] && this.config['mode'] != 'isSelectHidden' && this.config['isAlwaysShow'] !== true){
            this.$closeBtn = $('<span class="closeBtn"></span>');
            this.$closeBtn.appendTo(this.$wrapper);
            this.$closeBtn.bind('click', function(){
                _this.hide();
                return false;
            });
        }         
        //初始化数据.       
        _this._getRootNodes(function(rootNodes){
            if(rootNodes && rootNodes.length){
                for(var i=0; i<rootNodes.length; i++){
                    if(rootNodes[i].attr){
                        rootNodes[i].attr['isRoot'] = 1;
                    }
                }
            }            
            if(_this.config['search'] !== false){
                _this._initSearchBox(rootNodes);
            } else {
                _this.$searchBox.remove();
            }
            _this._initNodeTree(rootNodes);
        });    
        //控件触发元素.
        this.$trigger = $($trigger); 
        if(this.config['isAlwaysShow'] !== true){   //若配置为始终显示，则不需要触发器.
            if($trigger.is(':text')){
                $trigger.addClass('treeNodeSelectorInput');
                $trigger.on({
                    'focus' : function(){
                        _this.$wrapper.show();
                    },
                    'click' : function(e){
                        return false;
                    }
                });
            } else {
                $trigger.on({
                    'click' : function(e){
                        _this.$wrapper.toggle();
                        return false;
                    }
                });
            }
        }        
        //点击页面其它位置，隐藏之.
        if(this.config['mode'] != 'isSelectHidden' && this.config['isAlwaysShow'] !== true){
            _this.$wrapper.hideOnClickDoc();
        }        
        this.$trigger.data('formField', this);
        this.$trigger.data('treeNodeSelector', this);
        
        _this.$container = this.config['isAlwaysShow'] !== true ? $trigger.parent() : $trigger;
        _this.$container.css('position', 'relative');
        //计算容器元素位置, 依赖于$container的尺寸，需要异步处理.
        (function(){
            var containerHeight = _this.$container.height() - 1,
                containerWidth = _this.$container.width();
            if(_this.config['pos'] == 'right'){                
                _this.$wrapper.css({
                    top : '0px',
                    left : containerWidth + 'px'
                });
            } else {
                _this.$wrapper.css({
                    width : containerWidth,
                    top : (_this.config['isAlwaysShow'] !== true) ? (containerHeight || 'auto') : 0
                });                
            } 
            if(_this.config['isAlwaysShow'] === true){
                _this.$wrapper.css({
                    width : '100%',
                    height : '100%'
                });
            }               
        }).defer(0);
        
        this.$wrapper.appendTo(this.$container);
        
        if(this.config['isAlwaysShow'] === true){
            this.$wrapper.show();
        }
        
        this.$container.data('formField', this);
    }.extend(ujs.ui.Component);
    
    /**
     * 初始化节点搜索框. 
     */
    _TreeNodeSelector.prototype._initSearchBox = function(rootNodes){
        var _this = this;
        _this.$searchBox.autoCompleteBox(Object.extend( true, 
            {               
                placeholder : 'search ...',
                isAlwaysShow : _this.config['isAlwaysShow'],
                closable : _this.config['stoneSep'],
                key : _this.config['key'],
                itemTmp : _this.config['searchBoxItemTmp'],
                listHeight : _this.$wrapper.height() - 28,
                events : {
                   'select' : function($item){                        
                        $item = $item.find('div');                
                        if(_this.fire(EVT_SelectNode, 
                            $item.attr('uid'), 
                            $item.text().trim(), 
                            $item.attr('icon'), 
                            {attr:{rel:'user'}}, 
                            $item
                       ) !== false){
                            if(_this.config['isAlwaysShow'] !== true){
                                _this.hide();
                            }
                        }
                    }
               }
            }, 
            Type.isFunction(_this.config['searchBoxConfig']) ? 
                _this.config['searchBoxConfig'](rootNodes) : 
                _this.config['searchBoxConfig']
        ));        
    };
    
    _TreeNodeSelector.prototype._initNodeTree = function(rootNodes, initSelectedID){
        var _this = this,
            treeCoreConfig = {
                load_open : true
            };
            
        if(_this.config['initially_open'] !== false){
            if(rootNodes.length > 0 && rootNodes[0].attr){
                treeCoreConfig['initially_open'] = [ rootNodes[0].attr.id ];
            }
        }
        
        _this.$tree.jstree(Object.extend(true, {
            plugins : ["themes", "json_data", "ui" , "types"],
            core : treeCoreConfig,   
            ui : {
                selected_parent_close : false
            },
            types : {
                types : {
                    folder : {
                        icon : { image : ujs.getRes('images/common16/category.png') }                           
                    },
                    leaf : {
                        icon : { image : ujs.getRes('images/common16/leaf.png') }
                    }
                }
            },
            json_data : {
                data : rootNodes,
                ajax : {
                    beforeSend: function(jqXHR, settings) {                    	
                        jqXHR.url = settings.url;
                    },
                    success : ujs.hr(function(data, textStatus, jqXHR){                            
                        var dataAdapter = _this.config['dataAdapter'];
                        if(dataAdapter){
                            return dataAdapter.parse(data);
                        } else {
                            var nodes = null;                                      
                            var groups = data['userGroups'] || [];
                            for(var i = 0; i < groups.length; i++) {
                                groups[i]['rel'] = 'group';
                                groups[i]['state'] = 'closed'; 
                            }                            
                            var users2 = [];
                            if(_this.config['noUser'] !== true){
                                var users = data['users'] || [];
                                for(var j = 0; j < users.length; j++) {
                                    users[j]['rel'] = 'user'; 
                                    if(true || !_this.config['exclusion'].contains(users[j]['id'])){
                                        users2.push(users[j]);
                                    }
                                }
                            }
                            nodes = $.merge(_this.config['noGroup'] === true ? [] : groups, users2);
                            return _this.dataAdapter.parse(nodes);
                        }                     
                    })
                }
            }
        }, _this.config['treeConfig'], (initSelectedID ? {
            ui : {
                initially_select : [ initSelectedID ]
            }
        } : {}) )).bind('select_node.jstree', function(e, data) {  
            if($(data.rslt.obj).attr('cr')){
                return false;
            }          
            //选择节点.
            var node = _this.tree.get_json(data.rslt.obj)[0],
                nodeID = _this.config['useGuid'] ? ($(data.rslt.obj).attr('guid') || $(data.rslt.obj).attr('id')) : node.attr['id'],
                nodeText = node.data,
                nodeIcon = data.rslt.obj.attr('icon');            
                
            if(_this.config['exclusion'].contains(nodeID)){
                return false;
            }
                     
            if(_this.fire(EVT_SelectNode, nodeID, nodeText, nodeIcon, node) !== false){
                if(_this.$trigger.is(':text')){
                    _this.$container.attr('selectedvalue', nodeID);
                    _this.$trigger.val(nodeText); 
                }
                //点击节点后，隐藏tree。
                //若自定义selectNode事件返回false, 则不走当前判断分支。
                if(_this.config['mode'] != 'isSelectHidden'){
                    if(_this.config['isAlwaysShow'] !== true)
                        _this.hide();
                }
            }
        });
                         
        _this.tree = $.jstree.getJsTreeObj(_this.$tree);     
    };
    
    /**
     * 获取根节点.
     * @private
     */
    _TreeNodeSelector.prototype._getRootNodes = function(cb, isForceRefresh){
        var _this = this,
            rootNodes;
            
        //现成的根节点数据用Array传递。
        if(Type.isArray(_this.config['root'])){
            rootNodes = _this.config['root'];            
            if(this.dataAdapter){
                rootNodes = this.dataAdapter.parse(rootNodes); 
            }
            _this.rootNodes = rootNodes;
            cb && cb(rootNodes || []);            
        }
        //使用ajax获取根节点数据， 参数配置ajax请求参数.
        if(Type.isObject(_this.config['root'])){         
            $.ajax(Object.extend(true, {}, _this.config['root']))
            .done(ujs.hr(function(data){
                rootNodes = [];
                var dataAdapter = _this.config['dataAdapter'];
                if(dataAdapter){
                    rootNodes = dataAdapter.parse(data);
                } else {
                    var roots = data['userGroups'];               
                    for(var i=0; i<roots.length; i++){                    
                        rootNodes.push({ 
                            attr : { 
                                id : roots[i]['id'],
                                icon : roots[i]['icon'],
                                rel : roots[i]['cr'] ? 'cr' : 'group',
                                cr : roots[i]['cr'] //特定代码，删掉
                            }, 
                            data : roots[i]['name'],
                            state: 'closed'
                        });
                    }
                }                 
                _this.fire(EVT_RootLoaded, rootNodes);
                _this.rootNodes = rootNodes;
                cb && cb(rootNodes || []);
            }));
        }
        return this;
    };
    
    //----------------------------------------------------------------------
    
    /**
     * 获取选中的节点ID. 
     */
    _TreeNodeSelector.prototype.getValue = function(){
        if(this.config['isAlwaysShow'] !== true){
            if(this.$trigger.is(':text')){
                return this.$container.attr('selectedvalue');
            }
        } else {
            var $node = this.getSelectedNode();
            var nodeID = $node.attr('id');
            return nodeID;
        } 
    };
    _TreeNodeSelector.prototype.getSelectedID = _TreeNodeSelector.prototype.getValue;
    
    /**
     * 获取选中的节点数据. 
     */
    _TreeNodeSelector.prototype.getSelectedData = function(){
        var nodeID = this.getSelectedID();
        if(nodeID && this.tree.rawData){
            return this.tree.rawData[nodeID];
        }
    };
    
    //----------------------------------------------------------------------
    
    /**
     * 获取当前节点.
     */
    _TreeNodeSelector.prototype.getSelectedNode = function(){        
        return this.tree.get_selected();
    };    
    /**
     * 获取当前节点的父节点.
     */
    _TreeNodeSelector.prototype.getParentNode = function(){        
        var tree = this.tree,
            $selectedNode = tree.get_selected();
        return tree._get_parent($selectedNode);
    };
    /**
     * 刷新根节点.
     * TODO:可能会造成事件的多次注册.
     *
     */
    _TreeNodeSelector.prototype.refreshRoots = function(rootNodes, initSelectedID){
    	var _this = this;        
    	if(!rootNodes){
            _this._getRootNodes(function(rootNodes){
            	//TODO:可能会造成事件的多次注册.            
                _this._initNodeTree(rootNodes);
            }, true);   
        } else {
            if(this.dataAdapter){
                rootNodes = this.dataAdapter.parse(rootNodes); 
            }
            _this.rootNodes = rootNodes;
            _this._initNodeTree(rootNodes, initSelectedID);
        }
    };        
    /**
     * 刷新当前节点.
     */
    _TreeNodeSelector.prototype.refreshNode = function(){
        this.tree.refresh(this.tree.get_selected());
    };    
    /**
     * 删除当前节点.
     */
    _TreeNodeSelector.prototype.delNode = function(){        
        this.tree.delete_node(this.tree.get_selected());
        return this;     
    };    
    /**
     * 刷新当前节点的父节点.
     */
    _TreeNodeSelector.prototype.refreshParentNode = function(){
        var tree = this.tree,
            $selectedNode = tree.get_selected(),
            $parentNode = tree._get_parent($selectedNode);        
        tree.refresh($parentNode);
        return this;
    };
            
    //-----------------------------------------------------------------------
            
    $.fn.treeNodeSelector = function(config){        
        this.each(function(){        	
            new _TreeNodeSelector(this, config);
        });
        return this;
    };
    
})(jQuery);